﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;

namespace CustomUtils
{
	#region Text Convert

	[ComVisible(true)]
	[Guid("606B42CC-4187-4362-9CF4-BC44D537D12C")]
	[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
	public interface IConverter
	{
		string Convert(string srcEncodingName, string destEncodingName, string text);
	}

	[Guid("ECD87E3D-8781-40A7-9E62-16335A50666D")]
	[ClassInterface(ClassInterfaceType.AutoDual)]
	[ComSourceInterfaces(typeof (IConverter))]
	public class Converter
	{
		/*
		/// <summary>
		///     Перекодувати текст
		/// </summary>
		/// <param name="srcCodepage">Кодова сторінка кодування вхідного тексту</param>
		/// <param name="destEncodingName">Назва кодування вихідного тексту</param>
		/// <param name="text">Вхідний текст</param>
		/// <returns></returns>
		public string Convert(int srcCodepage, string destEncodingName, string text)
		{
			var srcEncoding = Encoding.GetEncoding(srcCodepage);
			var destEncoding = Encoding.GetEncoding(destEncodingName);
			return Convert(destEncoding, srcEncoding, text);
		}

		/// <summary>
		///     Перекодувати текст
		/// </summary>
		/// <param name="srcEncodingName">Назва кодування вхідного тексту</param>
		/// <param name="destCodepage">Кодова сторінка кодування вихідного тексту</param>
		/// <param name="text">Вхідний текст</param>
		/// <returns></returns>
		public string Convert(string srcEncodingName, int destCodepage, string text)
		{
			var srcEncoding = Encoding.GetEncoding(srcEncodingName);
			var destEncoding = Encoding.GetEncoding(destCodepage);

			return Convert(destEncoding, srcEncoding, text);
		}

		/// <summary>
		///     Перекодувати текст
		/// </summary>
		/// <param name="srcCodepage">Кодова сторінка кодування вхідного тексту</param>
		/// <param name="destCodepage">Кодова сторінка кодування вихідного тексту</param>
		/// <param name="text">Вхідний текст</param>
		/// <returns></returns>
		public string Convert(int srcCodepage, int destCodepage, string text)
		{
			var srcEncoding = Encoding.GetEncoding(srcCodepage);
			var destEncoding = Encoding.GetEncoding(destCodepage);
			return Convert(destEncoding, srcEncoding, text);
		}
		*/

		/// <summary>
		///     Перекодувати текст
		/// </summary>
		/// <param name="srcEncodingName">Назва кодування вхідного тексту</param>
		/// <param name="destEncodingName">Назва кодування вихідного тексту</param>
		/// <param name="text">Вхідний текст</param>
		/// <returns></returns>
		public string Convert(string srcEncodingName, string destEncodingName, string text)
		{
			var srcEncoding = Encoding.GetEncoding(srcEncodingName);
			var destEncoding = Encoding.GetEncoding(destEncodingName);

			return Convert(destEncoding, srcEncoding, text);
		}

		/// <summary>
		///     Перекодувати текст
		/// </summary>
		/// <param name="srcEncoding">Кодування вхідного тексту</param>
		/// <param name="destEncoding">Кодування вихідного тексту</param>
		/// <param name="text">Вхідний текст</param>
		/// <returns></returns>
		private string Convert(Encoding srcEncoding, Encoding destEncoding, string text)
		{
			return srcEncoding.GetString(Encoding.Convert(destEncoding, srcEncoding, srcEncoding.GetBytes(text)));
		}
	}

	#endregion Text Convert

	#region Work Hours Class

	[ComVisible(true)]
	[Guid("1A83F873-3835-49D2-B4D6-E6EA92508E0E")]
	[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
	public interface IWorkDateTime
	{
		void SetWorkDaysOfWeek(int d);
		void SetHolidayDates(object d);
		void SetHolidayDatesFromStringDateArray(string[] d);
		void SetHolidayDatesFromString(string d);
		void SetWorkStartTime(int hours, int minutes);
		void SetWorkFinishTime(int hours, int minutes);
		int GetWorkMinutes(DateTime startDateTime, DateTime finishDateTime);
		int GetWorkDayMinutes(DateTime d);
	}

	[Guid("92FFB411-564C-4321-A100-AB5947282EB8")]
	[ClassInterface(ClassInterfaceType.AutoDual)]
	[ComSourceInterfaces(typeof (IWorkDateTime))]
	public class WorkDateTime
	{
		private DateTime _finishDt;
		private int _finishWorkMinutes = 18*60;

		private DateTime _startDt;
		private int _startWorkMinutes = 9*60;
		private int _workDaysOfWeek = 5;

		private DateTime[] _holidays;

		/// <summary>
		///     Встановити кількість робочох днів на тиждень починаючи з понеділка
		/// </summary>
		/// <param name="d">Кількість днів</param>
		public void SetWorkDaysOfWeek(int d)
		{
			_workDaysOfWeek = (1 > d || 7 < d) ? 5 : d;
		}

		/// <summary>
		///     Встановити дати вихідних днів
		/// </summary>
		/// <param name="d">Масив дат</param>
		public void SetHolidayDates(DateTime[] d)
		{
			_holidays = d;
		}

		/// <summary>
		///     Встановити дати вихідних днів з текстового масиву дат
		/// </summary>
		/// <param name="d">Текстовий масив дат</param>
		public void SetHolidayDatesFromStringDateArray(string[] d)
		{
			try
			{
				_holidays = d.Select(DateTime.Parse).ToArray();
			}
			catch (Exception)
			{
			}
		}

		/// <summary>
		///     Встановити дати вихідних днів з текстового рядка дат розділених крапкою з комою
		/// </summary>
		/// <param name="d">Текстовий рядок дат розділених крапкою з комою</param>
		public void SetHolidayDatesFromString(string d)
		{
			try
			{
				_holidays = d.Trim(';').Split(';').Select(DateTime.Parse).ToArray();
			}
			catch (Exception)
			{
			}
			
		}

		/// <summary>
		///     Встановити час початку робочого дня
		/// </summary>
		/// <param name="hours">години (24-й формат)</param>
		/// <param name="minutes">хвилини</param>
		public void SetWorkStartTime(int hours, int minutes)
		{
			var h = (0 > hours || 23 < hours) ? 9*60 : hours*60;
			var m = (0 > minutes || 60 < minutes) ? 0 : minutes;
			_startWorkMinutes = h + m;
		}
		
		/// <summary>
		///     Встановити час завершення робочого дня
		/// </summary>
		/// <param name="hours">години (24-й формат)</param>
		/// <param name="minutes">хвилини</param>
		public void SetWorkFinishTime(int hours, int minutes)
		{
			var h = (0 > hours || 23 < hours) ? 9*60 : hours*60;
			var m = (0 > minutes || 60 < minutes) ? 0 : minutes;
			_finishWorkMinutes = h + m;
		}
		
		/// <summary>
		///     Порахувати тривалість роботи на вказаному проміжку часу
		/// </summary>
		/// <param name="startDateTime">Час початку</param>
		/// <param name="finishDateTime">Час завершення</param>
		/// <returns>Тривалість роботи у хвилинах</returns>
		public int GetWorkMinutes(DateTime startDateTime, DateTime finishDateTime)
		{
			if (startDateTime.Date == finishDateTime.Date)
			{
				if (null != _holidays && _holidays.Any(item => item.Date == startDateTime.Date))
				{
					return 0;
				}

				var m = finishDateTime.Hour*60 + finishDateTime.Minute;

				var finishMinutes = m > _finishWorkMinutes ? _finishWorkMinutes : m;


				m = startDateTime.Hour * 60 + startDateTime.Minute;

				var startMinutes = m >= _startWorkMinutes ? (m > finishMinutes ? finishMinutes : m) : _startWorkMinutes;

				
				return finishMinutes - startMinutes;
			}

			_startDt = startDateTime;
			_finishDt = finishDateTime;

			var dateList = new List<DateTime> {_startDt};
			var d = _startDt.AddDays(1);

			while (d.Date < _finishDt.Date)
			{
				dateList.Add(d);
				d = d.AddDays(1);
			}
			dateList.Add(_finishDt);

			return dateList.Where(item => (_workDaysOfWeek >= (int)item.DayOfWeek) && (0 < (int)item.DayOfWeek)).Sum(item => GetWorkDayMinutes(item));
		}

		/// <summary>
		///     Порахувати тривалість роботи на вказану дату
		/// </summary>
		/// <param name="d">Дата</param>
		/// <returns>Тривалість роботи у хвилинах</returns>
		public int GetWorkDayMinutes(DateTime d)
		{
			if (null != _holidays && _holidays.Any(item => item.Date == d.Date))
			{
				return 0;
			}

			if (d.Date == _startDt.Date)
			{
				var m = d.Hour * 60 + d.Minute;
				var startMinutes = m >= _startWorkMinutes ? m : _startWorkMinutes;

				var diff = _finishWorkMinutes - startMinutes;
				return diff >= 0 ? diff : 0;
			}

			if (d.Date == _finishDt.Date)
			{
				var m = d.Hour * 60 + d.Minute;
				var finishMinutes = m <= _finishWorkMinutes ? m : _finishWorkMinutes;
				var diff = finishMinutes - _startWorkMinutes;
				return diff >= 0 ? diff : 0;
			}

			return _finishWorkMinutes - _startWorkMinutes;
		}
	}

	#endregion Work Hours Class

	#region Translit

	[ComVisible(true)]
	[Guid("7ACAB217-E9F1-419E-A921-09BB757E6D7D")]
	[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
	public interface ITranslit
	{
		string Front(string text);
		string Back(string text);
	}
	
	[ClassInterface(ClassInterfaceType.AutoDual)]
	[ComSourceInterfaces(typeof(ITranslit))]
	[Guid("2D2048B8-9280-443E-B787-427BDB04A492")]
	public class Translit
	{
		private Dictionary<string, string> iso = new Dictionary<string, string>(); 

		public string Front(string text)
		{
			return iso.Aggregate(text, (current, key) => current.Replace(key.Key, key.Value));
		}

		public string Back(string text)
		{
			return iso.Aggregate(text, (current, key) => current.Replace(key.Value, key.Key));
		}

		public Translit()
		{
			iso.Add("Є", "YE");
			iso.Add("І", "I");
			iso.Add("Ѓ", "G");
			iso.Add("і", "i");
			iso.Add("№", "#");
			iso.Add("є", "ye");
			iso.Add("ѓ", "g");
			iso.Add("А", "A");
			iso.Add("Б", "B");
			iso.Add("В", "V");
			iso.Add("Г", "G");
			iso.Add("Д", "D");
			iso.Add("Е", "E");
			iso.Add("Ё", "YO");
			iso.Add("Ж", "ZH");
			iso.Add("З", "Z");
			iso.Add("И", "I");
			iso.Add("Й", "J");
			iso.Add("К", "K");
			iso.Add("Л", "L");
			iso.Add("М", "M");
			iso.Add("Н", "N");
			iso.Add("О", "O");
			iso.Add("П", "P");
			iso.Add("Р", "R");
			iso.Add("С", "S");
			iso.Add("Т", "T");
			iso.Add("У", "U");
			iso.Add("Ф", "F");
			iso.Add("Х", "X");
			iso.Add("Ц", "C");
			iso.Add("Ч", "CH");
			iso.Add("Ш", "SH");
			iso.Add("Щ", "SCH");
			iso.Add("Ъ", "'");
			iso.Add("Ы", "Y");
			iso.Add("Ь", "");
			iso.Add("Э", "E");
			iso.Add("Ю", "YU");
			iso.Add("Я", "YA");
			iso.Add("а", "a");
			iso.Add("б", "b");
			iso.Add("в", "v");
			iso.Add("г", "g");
			iso.Add("д", "d");
			iso.Add("е", "e");
			iso.Add("ё", "yo");
			iso.Add("ж", "zh");
			iso.Add("з", "z");
			iso.Add("и", "i");
			iso.Add("й", "j");
			iso.Add("к", "k");
			iso.Add("л", "l");
			iso.Add("м", "m");
			iso.Add("н", "n");
			iso.Add("о", "o");
			iso.Add("п", "p");
			iso.Add("р", "r");
			iso.Add("с", "s");
			iso.Add("т", "t");
			iso.Add("у", "u");
			iso.Add("ф", "f");
			iso.Add("х", "x");
			iso.Add("ц", "c");
			iso.Add("ч", "ch");
			iso.Add("ш", "sh");
			iso.Add("щ", "sch");
			iso.Add("ъ", "");
			iso.Add("ы", "y");
			iso.Add("ь", "");
			iso.Add("э", "e");
			iso.Add("ю", "yu");
			iso.Add("я", "ya");
			iso.Add("«", "");
			iso.Add("»", "");
			iso.Add("—", "-");
		}
	}

	#endregion Translit

	#region Parser

	[ComVisible(true)]
	[Guid("3F37E3EB-0581-4BB9-9D7F-EE915DEAEF22")]
	[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
	public interface IParser
	{
		string GetMessageDataString(string text);
	}

	[ClassInterface(ClassInterfaceType.AutoDual)]
	[ComSourceInterfaces(typeof(ITranslit))]
	[Guid("23C5A6DE-9730-4806-A071-DD6FB933FEE5")]
	public class Parser
	{
		public string GetMessageDataString(string text)
		{
			var s = @"
ssdfgsdfg


Имя клиента: test name
Телефон: test tel
Обратный E-Mail: testemail@mail.ru
Сайт: Фасад Каркас

==================================
test texttest texttest texttest texttest texttest texttest texttest texttest texttest texttest text";
			var re = new Regex(@"(.|\W)*^Имя клиента: (.*)$\W*^Телефон: (.*)$\W*Обратный E-Mail: (.*)$\W*Сайт: (.*)$\W*=+\W*((.|\W)*)", RegexOptions.Multiline);
			var r = re.Match(s);
			var z = r;
			return "";
		}
	}

	#endregion Parser
}